#ifndef _UIEDIT_H
#define _UIEDIT_H
#include<Windows.h>
#include<string>
#include<TCHAR.h>
#include<vector>
#include<algorithm>
using std::vector;

#ifdef UNICODE
using std::wstring;
typedef wstring tstring;
#else
using std::string;
typedef string tstring;
#endif

#define		UIEVENT_CHAR					0x0001
#define		UIEVENT_LBUTTONDOWN		0x0002
#define		UIEVENT_LBUTTONUP			0x0003
#define		UIEVENT_MOUSEMOVE			0x0004
#define		UIEVENT_SETFOCUS				0x0005
#define		UIEVENT_KEYDOWN				0x0006
#define		UIEVENT_LBUTTONDBCLK		0x0007
#define		UIEVENT_RBUTTONDOWN	0x0008
#define		UIEVENT_SIZE						0x0009

typedef struct tagTEVENTUI
{	
	UINT Type;
	WPARAM wParam;
	LPARAM lParam;
	POINT pt;
}TEventUI;

class CMyEdit
{
public:
	CMyEdit(HWND hWnd);
	virtual ~CMyEdit();
	typedef vector<unsigned> CUintArray;
	typedef vector<CUintArray> C2DimenUintArray;
	typedef vector<tstring> CStringArray;

	typedef struct tagCHARPOS
	{
		unsigned paraIndex;
		unsigned lineIndex;
		unsigned charIndex;
	}CharPos;
	
	typedef struct tagINDEXINFO
	{
		unsigned paraIndex;
		unsigned index;
	}IndexInfo;

public:
	int GetLineCount();
	int GetFirstVisibleLine();
	void Copy();
	void Cut();
	void Paste();
public:
	virtual void Render(HDC hDestDC);
	virtual bool Event(TEventUI& event);
	virtual void Init();
public:
	BOOL CreateCaret(int nWidth, int nHeight);
	BOOL SetCaretPos(int x, int y);
	BOOL ShowCaret();
	BOOL HideCaret();
protected:
	void OnKeyDown(UINT nChar, UINT nFlags);
	void OnChar(UINT nChar, UINT nFlags);
	void OnLButtonDown(UINT nFlags, POINT pt);
	void OnRButtonDown(UINT nFlags, POINT pt);
	void OnLButtonUp(UINT nFlags, POINT pt);
	void OnLButtonDblClk(UINT nFlags, POINT pt);
	void OnMouseMove(UINT nFlags, POINT pt);
	void OnSize(UINT nType, int cx, int cy);
protected:
	void GetClientRect(RECT &rc);
	void GetSel(tstring &str);
	void CharPos2IndexInfo(const CharPos &pos, IndexInfo &indexInfo);
	void IndexInfo2CharPos(const IndexInfo &indexInfo, CharPos &pos);
	void CharPos2Point(const CharPos &pos, POINT &point);
	void Point2CharPos(const POINT &point, CharPos &pos);

	tstring GetLeftLineString(const CharPos &pos);
	tstring GetLineString(const unsigned paraNum, const unsigned nLine);
	LPCTSTR GetCharPosStr(const CharPos &pos);
	void AdjustParaLineCharCounts(unsigned paraNum, unsigned ingore = 0);
	
	BOOL DeleteSelRange();
	bool EnsureSelEndVisible();
	
	void UpSelEnd();
	void LeftSelEnd();
	void RightSelEnd();
	void DownSelEnd();
	void BackSelEnd();
	void DrawRange(HDC hDC, const CharPos &beginPos, const CharPos &endPos);
private:
	void CalLhAcw();
	void Insert(const TCHAR *lpszText);
	void InsertNocrlf(LPCTSTR lpszNewText, int count);
	bool AdjustStringLine(const TCHAR *lpszText, CUintArray &uintArray, unsigned ingore = 0);
	int CutStringForOneLine(HDC hDC, const TCHAR *lpszText, int width);
	BOOL TextOut(HDC hDC, int x, int y, LPCTSTR lpszText, int c);
private:
	RECT						m_rcInset;
	RECT						m_RectInit;
	HWND						m_hParentWnd;
public:
	RECT GetInset();
	void GetInitPos(int &l, int &t, int &r, int &b);
	void GetInitPos(RECT &rc);
	RECT GetInterRect();
	void Invalidate(BOOL nFlag = FALSE);
	void InvalidateRect(LPRECT lpRect, BOOL nFlag = FALSE);

private:
	RECT GetInsertReDrawRect(const CharPos &beginPos, const POINT &beginPt, const CharPos &endPos, 
		const POINT &endPt, const unsigned uPrevTimesParaLines, const unsigned uCurTimesParalines);
	RECT GetDelReDrawRect(const CharPos &beginPos, const POINT &beginPt, const CharPos &endPos, 
		const POINT &endPt, const unsigned uPrevTimesParaLines, const unsigned uCurTimesParalines);
	RECT GetSelReDrawRect();
private:	
	CStringArray				m_szTextArray;
	C2DimenUintArray		m_LineCharCountsArray;
	int								m_FirstVisibleLine;
	int								m_LineHeight;
	int								m_AveCharWidth;
	CharPos					m_selBegin;
	CharPos					m_selEnd;
	CharPos					m_prevSelEnd;
	unsigned					m_clientWidth;
	unsigned					m_clientHeight;
	HFONT						m_hFont;
	COLORREF				m_inputBkColor;
	COLORREF				m_textColor;
	COLORREF				m_selBkColor;
	COLORREF				m_selTextColor;
};


#endif